﻿using ControlzEx.Standard;
using DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Drawing.Charts;
using DocumentFormat.OpenXml.Drawing.Wordprocessing;
using DocumentFormat.OpenXml.Linq;
using DocumentFormat.OpenXml.Office2010.Excel;
using DocumentFormat.OpenXml.Presentation;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml.Wordprocessing;
using ExCSS;
using MahApps.Metro.Controls;
using NPOI.OpenXmlFormats.Wordprocessing;
using NPOI.SS.Formula.Functions;
using NPOI.XWPF.UserModel;
using ShapeCrawler;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web.UI.WebControls;
using System.Windows.Documents;
using System.Windows.Media.Media3D;
using static Microsoft.WindowsAPICodePack.Shell.PropertySystem.SystemProperties.System;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor.Utils.NPOIHelp
{
    public class 演示文稿管理器
    {
        public 演示文稿管理器(幻灯片尺寸 size = 幻灯片尺寸.标准幻灯片)
        {
            var path = Globals.InstalledPath + "PptxTemplates\\";
            var fileName = "";
            switch (size)
            {
                case 幻灯片尺寸.标准幻灯片:
                    fileName = "01";
                    break;
                case 幻灯片尺寸.信纸幻灯片:
                    fileName = "02";
                    break;
                case 幻灯片尺寸.分类账幻灯片:
                    fileName = "03";
                    break;
                case 幻灯片尺寸.A3幻灯片:
                    fileName = "04";
                    break;
                case 幻灯片尺寸.A4幻灯片:
                    fileName = "05";
                    break;
                case 幻灯片尺寸.B4幻灯片:
                    fileName = "06";
                    break;
                case 幻灯片尺寸.B5幻灯片:
                    fileName = "07";
                    break;
                case 幻灯片尺寸.顶置幻灯片:
                    fileName = "08";
                    break;
                case 幻灯片尺寸.横幅幻灯片:
                    fileName = "09";
                    break;
                case 幻灯片尺寸.全屏幻灯片:
                    fileName = "10";
                    break;
                case 幻灯片尺寸.高全屏幻灯片:
                    fileName = "11";
                    break;
                case 幻灯片尺寸.宽屏幻灯片:
                    fileName = "12";
                    break;
                case 幻灯片尺寸.纵向A4幻灯片:
                    fileName = "13";
                    break;
                default:
                    _演示文稿体 = new ShapeCrawler.Presentation();
                    return;
            }

            _演示文稿体 = new ShapeCrawler.Presentation(path + fileName + ".pptx");

            // 注意这里的顺序，先添加空白幻灯片，再删除原有的，不然会出错。
            _演示文稿体.Slides.AddEmptySlide(SlideLayoutType.Blank);
            for (int i = _演示文稿体.Slides.Count - 2; i >= 0; i--)
            {
                var slide = _演示文稿体.Slides[i];
                _演示文稿体.Slides.Remove(slide);
            }
        }

        public 演示文稿管理器(string path)
        {
            _文件路径 = path;
            _演示文稿体 = new ShapeCrawler.Presentation(path);
        }

        private ShapeCrawler.Presentation _演示文稿体;

        public ShapeCrawler.Presentation 演示文稿体
        {
            get { return _演示文稿体; }
        }

        public decimal 幻灯片宽度
        {
            get
            {
                if (_演示文稿体 == null) return 0;

                return _演示文稿体.SlideWidth;
            }
            set
            {
                if (_演示文稿体 == null) return;

                _演示文稿体.SlideWidth = value;
            }
        }

        public decimal 幻灯片高度
        {
            get
            {
                if (_演示文稿体 == null) return 0;

                return _演示文稿体.SlideHeight;
            }
            set
            {
                if (_演示文稿体 == null) return;

                _演示文稿体.SlideHeight = value;
            }
        }

        public 幻灯片 添加幻灯片(幻灯片布局 layout = 幻灯片布局.空白布局)
        {
            var _幻灯片集 = 幻灯片集;
            if (_幻灯片集 == null) return null;

            return _幻灯片集.添加幻灯片(layout);
        }

        public 幻灯片 添加幻灯片(幻灯片 slide)
        {
            var _幻灯片集 = 幻灯片集;
            if (_幻灯片集 == null) return null;

            _幻灯片集.幻灯片集体.Add(slide.幻灯片体);
            return slide;
        }

        public 幻灯片 插入幻灯片(int position, 幻灯片布局 layout)
        {
            var _幻灯片集 = 幻灯片集;
            if (_幻灯片集 == null) return null;

            return _幻灯片集.插入幻灯片(position, layout);
        }

        public 幻灯片 插入幻灯片(int position, 幻灯片 slide)
        {
            var _幻灯片集 = 幻灯片集;
            if (_幻灯片集 == null) return null;

            return _幻灯片集.插入幻灯片(position, slide);
        }

        public void 移除幻灯片(int position)
        {
            var _幻灯片集 = 幻灯片集;
            if (_幻灯片集 == null) return;

            _幻灯片集.移除幻灯片(position);
        }

        public void 移除幻灯片(幻灯片 slide)
        {
            var _幻灯片集 = 幻灯片集;
            if (_幻灯片集 == null) return;

            _幻灯片集.移除幻灯片(slide);
        }

        public 幻灯片母版集 幻灯片母版集
        {
            get
            {
                if (_演示文稿体 == null) return null;

                return new 幻灯片母版集(_演示文稿体.SlideMasters);
            }
        }

        /// <summary>
        /// 一个 Section 中可包括多张幻灯片。
        /// </summary>
        public 幻灯片区块集 幻灯片区块集
        {
            get
            {
                if (_演示文稿体 == null) return null;

                return new 幻灯片区块集(_演示文稿体.Sections);
            }
        }

        public 幻灯片页脚 幻灯片页脚
        {
            get
            {
                if (_演示文稿体 == null) return null;

                return new 幻灯片页脚(_演示文稿体.Footer);
            }
        }

        private string _文件路径 = null;

        public string 文件路径
        {
            get { return _文件路径; }
        }

        /// <summary>
        /// “文件路径”会与 MarkdownEditor 类的同名属性同时出现在提示窗口中，不方便。
        /// </summary>
        public string 演示文稿路径
        {
            get { return _文件路径; }
        }

        public 文件 保存演示文稿()
        {
            try
            {
                if (_演示文稿体 == null) return null;

                if (File.Exists(_文件路径) == false)
                {
                    _文件路径 = InputBox.Show(Globals.AppName, "请输入文件名：", "新演示文稿", true);

                    var fi = new FileInfo(_文件路径);

                    return 另存演示文稿(fi.FullName);
                }

                _演示文稿体.Save();
                return new 文件(_文件路径);
            }
            catch
            {
                return null;
            }
        }

        public 文件 另存演示文稿(string path)
        {
            try
            {
                if (_演示文稿体 == null) return null;

                var fi = new FileInfo(path);
                _演示文稿体.SaveAs(path);
                return new 文件(path);
            }
            catch
            {
                return null;
            }
        }

        public 幻灯片集 幻灯片集
        {
            get
            {
                if (_演示文稿体 == null || _演示文稿体.Slides == null || _演示文稿体.Slides.Count == 0) return null;

                return new 幻灯片集(_演示文稿体.Slides, this);
            }
        }

        public int 幻灯片数量
        {
            get
            {
                var _幻灯片集 = 幻灯片集;
                if (_幻灯片集 == null) return 0;

                return _幻灯片集.幻灯片数量;
            }
        }

        public 幻灯片 首幻灯片
        {
            get
            {
                var _幻灯片集体 = this.幻灯片集;
                if (_幻灯片集体 == null || _幻灯片集体.幻灯片数量 <= 0) return null;

                return _幻灯片集体.首幻灯片;
            }
        }

        public 幻灯片 尾幻灯片
        {
            get
            {
                var _幻灯片集体 = this.幻灯片集;
                if (_幻灯片集体 == null || _幻灯片集体.幻灯片数量 <= 0) return null;

                return _幻灯片集体.尾幻灯片;
            }
        }

        static 演示文稿管理器()
        {
            默认形状样式 = new 形状样式();

            题干形状样式 = new 形状样式() { 形状字体 = "Microsoft Yahei", 形状字号 = 24, };
            题支形状样式 = new 形状样式() { 形状字体 = "Microsoft Yahei", 形状字号 = 24, };
            标题形状样式1 = new 形状样式() { 形状字体 = "Microsoft Yahei", 形状字号 = 24, };
            标题形状样式2 = new 形状样式() { 形状字体 = "Microsoft Yahei", 形状字号 = 22, };
            标题形状样式3 = new 形状样式() { 形状字体 = "Microsoft Yahei", 形状字号 = 20, };
            标题形状样式4 = new 形状样式() { 形状字体 = "Microsoft Yahei", 形状字号 = 18, };
            正文形状样式 = new 形状样式() { 形状字体 = "Microsoft Yahei", 形状字号 = 16, };
        }

        public static 形状样式 默认形状样式 { get; }

        public static 形状样式 题干形状样式 { get; }

        public static 形状样式 题支形状样式 { get; }

        public static 形状样式 标题形状样式1 { get; }

        public static 形状样式 标题形状样式2 { get; }

        public static 形状样式 标题形状样式3 { get; }

        public static 形状样式 标题形状样式4 { get; }

        public static 形状样式 正文形状样式 { get; }
    }

    public class 形状样式
    {
        public int 横坐标 { get; set; } = 0;

        public int X
        {
            get => 横坐标;
            set => 横坐标 = value;
        }

        public int 纵坐标 { get; set; } = 0;

        public int Y
        {
            get => 纵坐标;
            set => 纵坐标 = value;
        }

        public int 宽度 { get; set; } = 200;

        public int 高度 { get; set; } = 50;

        public bool 报表坐标系 { get; set; } = false;

        public string 形状字体 { get; set; } = "Microsoft Yahei";

        public decimal 形状字号 { get; set; } = 24;

        public bool 形状加粗 { get; set; } = false;

        public bool 形状倾斜 { get; set; } = false;

        public 形状下划线类型 形状下划线类型 { get; set; } = 形状下划线类型.形状无下划线;

        public string 形状前景色 { get; set; } = "000000";

        public string 形状背景色 { get; set; } = "";

        public decimal 形状边框宽 { get; set; } = 1;

        public decimal 形状边框宽度
        {
            get => 形状边框宽;
            set => 形状边框宽 = value;
        }

        public string 形状边框色 { get; set; } = "000000";
    }

    public enum 幻灯片尺寸
    {
        标准幻灯片,  // 4:3
        信纸幻灯片,
        分类账幻灯片,
        A3幻灯片,
        A4幻灯片,
        B4幻灯片,
        B5幻灯片,
        顶置幻灯片,
        横幅幻灯片,
        全屏幻灯片,    // 16:9
        高全屏幻灯片,  // 16:10
        宽屏幻灯片,
        纵向A4幻灯片
    }

    public class 幻灯片报表
    {
        internal 幻灯片报表(幻灯片 slide, int rowsCount, int columnsCount,
            double pageSize1 = 1280, double pageSize2 = 720, bool isVertical = true,
            int left = 64, int top = 64, int right = 64, int bottom = 64, bool isVirtualReport = true)
        {
            _形状集 = slide.形状集;

            _行数 = rowsCount;
            _列数 = columnsCount;
            _左边距 = left;
            _上边距 = top;
            _右边距 = right;
            _下边距 = bottom;

            if (isVertical)
            {
                _页宽 = Math.Min(pageSize1, pageSize2);
                _页高 = Math.Max(pageSize1, pageSize2);
            }
            else
            {
                _页宽 = Math.Max(pageSize1, pageSize2);
                _页高 = Math.Min(pageSize1, pageSize2);
            }

            var baseWidth = (int)_页宽 / 4;
            var baseHeight = (int)_页高 / 4;

            if (left < 0) left = 0;
            if (left > baseWidth) left = baseWidth;

            if (top < 0) top = 0;
            if (top > baseHeight) top = baseHeight;

            if (right < 0) right = 0;
            if (right > baseWidth) right = baseWidth;

            if (bottom < 0) bottom = 0;
            if (bottom > baseHeight) bottom = baseHeight;

            _单位行高 = (int)(_页高 - _上边距 - _下边距) / _行数;
            _单位列宽 = (int)(_页宽 - _左边距 - _右边距) / _列数;
        }

        private 幻灯片 _所属幻灯片 = null;

        public 幻灯片 所属幻灯片
        {
            get { return _所属幻灯片; }
        }

        internal void 置所属幻灯片(幻灯片 slide)
        {
            this._所属幻灯片 = slide;
        }

        private bool _是否虚拟报表 = true;
        /// <summary>
        /// 报表是用直线部件在幻灯片上模拟表格——这样做效率很低，极耗内存。
        /// 但报表用于在插入形状时定位却又很方便。
        /// 添加这个属性用来阻止实例化报表的框线，但保留其用于定位的功能，方便添加部件。
        /// </summary>
        public bool 是否虚拟报表
        {
            get { return _是否虚拟报表; }
            set { _是否虚拟报表 = value; }
        }

        private 形状集 _形状集;

        public 形状集 形状集
        {
            get { return _形状集; }
        }

        private int _单位行高;

        public int 单位行高
        {
            get { return _单位行高; }
        }

        private int _单位列宽;

        public int 单位列宽
        {
            get { return _单位列宽; }
        }

        private double _页宽;

        public double 页宽 { get { return _页宽; } }

        private double _页高;

        public double 页高 { get { return _页高; } }

        private int _行数 = 10;
        /// <summary>
        /// 报表中应有几行。
        /// </summary>
        public int 行数
        {
            get { return _行数; }
            set { _行数 = value; }
        }

        private int _列数 = 10;
        /// <summary>
        /// 报表中应有几行。
        /// </summary>
        public int 列数
        {
            get { return _列数; }
            set { _列数 = value; }
        }

        private int _左边距 = 0;

        public int 左边距
        {
            get { return _左边距; }
            set { _左边距 = value; }
        }

        private int _上边距 = 0;

        public int 上边距
        {
            get { return _上边距; }
            set { _上边距 = value; }
        }

        private int _右边距 = 0;

        public int 右边距
        {
            get { return _右边距; }
            set { _右边距 = value; }
        }

        private int _下边距 = 0;

        public int 下边距
        {
            get { return _下边距; }
            set { _下边距 = value; }
        }

        /// <summary>
        /// 由报表调用“所属幻灯片”的对应方法。
        /// </summary>
        /// <param name="startPointX">起点横坐标，从0开始。</param>
        /// <param name="startPointY">起点纵坐标，从0开始。</param>
        /// <param name="endOffsetX">终点横坐标，从0开始。</param>
        /// <param name="endOffsetY">终点纵坐标，从0开始。</param>
        /// <param name="asReport">此参数总为真！</param>
        /// <returns></returns>
        public 形状 添加线条形状(int startPointX, int startPointY, int endOffsetX, int endOffsetY, bool asReport = true)
        {
            if (this._所属幻灯片 != null)
            {
                return this._所属幻灯片.添加线条形状(startPointX, startPointY, endOffsetX, endOffsetY, true);
            }
            return null;
        }

        /// <summary>
        /// 由报表调用“所属幻灯片”的对应方法。
        /// </summary>
        /// <param name="x">横坐标，从0开始。</param>
        /// <param name="y">纵坐标，从0开始。</param>
        /// <param name="width">宽度格数。</param>
        /// <param name="height">高度格数。</param>
        /// <param name="asReport">此参数总为真！</param>
        /// <returns></returns>
        public 形状 添加矩形形状(int x, int y, int width, int height, bool asReport = true)
        {
            if (this._所属幻灯片 != null)
            {
                return this._所属幻灯片.添加矩形形状(x, y, width, height, true);
            }
            return null;
        }

        /// <summary>
        /// 由报表调用“所属幻灯片”的对应方法。
        /// </summary>
        /// <param name="x">横坐标，从0开始。</param>
        /// <param name="y">纵坐标，从0开始。</param>
        /// <param name="width">宽度格数。</param>
        /// <param name="height">高度格数。</param>
        /// <param name="text">文本内容。</param>
        /// <param name="asReport">此参数总为真！</param>
        /// <param name="foreColor">前景色（RGB格式，不带 #）。</param>
        /// <param name="backColor">背景色（RGB格式，不带 #）。</param>
        /// <param name="fontEnName">字体英文名称。</param>
        /// <param name="fontSize">字号尺寸。</param>
        /// <param name="isBold">是否加粗。</param>
        /// <param name="isItalic">是否倾斜。</param>
        /// <param name="underLineType">下划线类型。</param>
        /// <param name="borderWeight">边框宽度。</param>
        /// <param name="borderColor">边框色（RGB格式，不带 #）。</param>
        /// <returns></returns>
        public 形状 添加文本块(int x, int y, int width, int height, string text, bool asReport = true,
                       string foreColor = "000000", string backColor = "FFFFFF",
                       string fontEnName = "simsun", decimal fontSize = 11,
                       bool isBold = false, bool isItalic = false, 形状下划线类型 underLineType = 形状下划线类型.形状无下划线,
                       decimal borderWeight = 0, string borderColor = "000000")
        {
            if (this._所属幻灯片 != null)
            {
                return this._所属幻灯片.添加文本块(x, y, width, height, text, true,
                       foreColor, backColor,
                       fontEnName, fontSize,
                       isBold, isItalic, underLineType,
                       borderWeight, borderColor);
            }
            return null;
        }

        /// <summary>
        /// 由报表调用“所属幻灯片”的对应方法。
        /// </summary>
        /// <param name="x">横坐标，从0开始。</param>
        /// <param name="y">纵坐标，从0开始。</param>
        /// <param name="path">声音文件完整磁盘路径。</param>
        /// <param name="asReport">此参数总为真！</param>
        /// <returns></returns>
        public 形状 添加声音形状(int x, int y, string path, bool asReport = true)
        {
            if (this._所属幻灯片 != null)
            {
                return this._所属幻灯片.添加声音形状(x, y, path, true);
            }
            return null;
        }

        /// <summary>
        /// 由报表调用“所属幻灯片”的对应方法。
        /// </summary>
        /// <param name="x">横坐标，从0开始。</param>
        /// <param name="y">纵坐标，从0开始。</param>
        /// <param name="path">视频文件完整磁盘路径。</param>
        /// <param name="asReport">此参数总为真！</param>
        /// <returns></returns>
        public 形状 添加视频形状(int x, int y, string path, bool asReport = true)
        {
            if (this._所属幻灯片 != null)
            {
                return this._所属幻灯片.添加视频形状(x, y, path, true);
            }
            return null;
        }

        /// <summary>
        /// 由报表调用“所属幻灯片”的对应方法。
        /// </summary>
        /// <param name="x">横坐标，从0开始。</param>
        /// <param name="y">纵坐标，从0开始。</param>
        /// <param name="width">宽度格数。</param>
        /// <param name="height">高度格数。</param>
        /// <param name="path"></param>
        /// <param name="asReport">此参数总为真！</param>
        /// <returns></returns>
        public 形状 添加图像形状(int x, int y, int width, int height, string path, bool asReport = true)
        {
            if (this._所属幻灯片 != null)
            {
                return this._所属幻灯片.添加图像形状(x, y, width, height, path, true);
            }
            return null;
        }

        /// <summary>
        /// 由报表调用“所属幻灯片”的对应方法。
        /// </summary>
        /// <param name="x">横坐标，从0开始。</param>
        /// <param name="y">纵坐标，从0开始。</param>
        /// <param name="width">宽度格数。</param>
        /// <param name="height">高度格数。</param>
        /// <param name="asReport">此参数总为真！</param>
        /// <returns></returns>
        public 形状 添加圆角矩形形状(int x, int y, int width, int height, bool asReport = true)
        {
            if (this._所属幻灯片 != null)
            {
                return this._所属幻灯片.添加圆角矩形形状(x, y, width, height, true);
            }
            return null;
        }

        /// <summary>
        /// 由报表调用“所属幻灯片”的对应方法。
        /// </summary>
        /// <param name="x">横坐标，从0开始。</param>
        /// <param name="y">纵坐标，从0开始。</param>
        /// <param name="columnsCount">列数。</param>
        /// <param name="rowsCount">行数。</param>
        /// <param name="asReport">此参数总为真！</param>
        /// <returns></returns>
        public 表格形状 添加表格形状(int x, int y, int width, int height, int columnsCount, int rowsCount, bool asReport = true)
        {
            if (this._所属幻灯片 != null)
            {
                return this._所属幻灯片.添加表格形状(x, y, width, height, columnsCount, rowsCount, true);
            }
            return null;
        }
    }

    public class 幻灯片
    {
        public 幻灯片(ISlide slide, 演示文稿管理器 masterPreManager)
        {
            _幻灯片体 = slide;
            _主文稿 = masterPreManager;
        }

        private 演示文稿管理器 _主文稿;

        public 演示文稿管理器 主文稿
        {
            get { return _主文稿; }
        }

        private ISlide _幻灯片体;

        public ISlide 幻灯片体
        {
            get { return _幻灯片体; }
        }

        private 幻灯片报表 _报表 = null;
        /// <summary>
        /// 用于在当前幻灯片中定义一些网格。
        /// </summary>
        public 幻灯片报表 报表
        {
            get { return _报表; }
        }

        public 形状集 形状集
        {
            get
            {
                if (_幻灯片体 == null || _幻灯片体.Shapes == null)
                {
                    return null;
                }

                return new 形状集(_幻灯片体.Shapes);
            }
        }

        public 形状 首形状
        {
            get
            {
                var _形状集 = 形状集;
                if (_形状集 == null || _形状集.形状个数 <= 0) return null;
                return _形状集.首形状;
            }
        }

        public 形状 尾形状
        {
            get
            {
                var _形状集 = 形状集;
                if (_形状集 == null || _形状集.形状个数 <= 0) return null;
                return _形状集.尾形状;
            }
        }

        private List<IShape> _报表边框集 = null;

        public List<IShape> 报表边框集
        {
            get => _报表边框集;
        }

        public 幻灯片报表 创建报表(int rowsCount, int columnsCount, int left = 64, int top = 64, int right = 64, int bottom = 64, bool isVirtualReport = true)
        {
            if (rowsCount < 1)
                throw new Exception("报表行数不能小于 1。");

            if (columnsCount < 1)
                throw new Exception("报表列数不能小于 1。");

            if (columnsCount < 1)
                throw new Exception("报表列数不能小于 1。");

            bool isVertical = false;
            var slideHeight = this._主文稿.演示文稿体.SlideHeight;
            var slideWidth = this._主文稿.演示文稿体.SlideWidth;
            if (slideHeight > slideWidth)
            {
                isVertical = true;
            }

            if (left < 0 || left > slideWidth)
                throw new Exception("左边距不能小于 0 或大于页面宽度。");

            if (right < 0 || right > slideWidth)
                throw new Exception("右边距不能小于 0 或大于页面宽度。");

            if (top < 0 || top > slideHeight)
                throw new Exception("上边距不能小于 0 或大于页面高度。");

            if (bottom < 0 || bottom > slideHeight)
                throw new Exception("下边距不能小于 0 或大于页面高度。");

            this._报表 = new 幻灯片报表(this, rowsCount, columnsCount, (double)slideHeight, (double)slideWidth, isVertical, left, top, right, bottom, isVirtualReport);
            this._报表.置所属幻灯片(this);

            if (this._报表边框集 != null && this._报表边框集.Count > 0)
            {
                for (int i = this._报表边框集.Count - 1; i >= 0; i--)
                {
                    if (this.幻灯片体.Shapes.Contains<IShape>(this._报表边框集[i]))
                    {
                        this.幻灯片体.Shapes.Remove(this._报表边框集[i]);
                    }
                }
            }

            if (isVirtualReport == false)  // 虚拟报表只用于在插入形状时定位，不需要绘制表格线条！
            {
                this._报表边框集 = new List<IShape>();

                // 绘制边框

                // 先绘制外边框
                var outBorder = this.添加矩形形状(0, 0, columnsCount, rowsCount, true);
                outBorder.置形状背景色("FFFFFF");  // 白色
                outBorder.置形状边框宽(2);

                // 再逐个绘制单元格位置对应右、下边框
                // 注意：这里不能整行/整列绘制，——因为要支持单元格自定义边框。
                for (int i = 0; i < rowsCount; i++)
                {
                    for (int j = 0; j < columnsCount; j++)
                    {
                        if (j < columnsCount - 1)
                        {
                            var vLine = this.添加线条形状(j + 1, i, 0, 1, true);  // 竖线（右侧）
                            vLine.置形状边框色("000000");
                        }

                        if (i < rowsCount - 1)
                        {
                            var hLine = this.添加线条形状(j, i + 1, 1, 0, true);  // 横线（底部）
                            hLine.置形状边框色("000000");
                        }
                    }

                    // Test 发现 Shape Carwler AddLine 方法有 Bug。
                    //if (i == 0)
                    //{
                    //    for (int j = 1; j < columnsCount - 1; j++)
                    //    {
                    //        this.添加线条形状(j, i, 0, 1, true).置形状边框色("FF0000");  // 竖线（右侧）
                    //        this.添加线条形状(j, i, 1, 0, true).置形状边框色("FF00FF");  // 横线（底部）
                    //    }
                    //}
                    //else
                    //{
                    //    for (int j = 1; j < columnsCount - 1; j++)
                    //    {
                    //        this.添加线条形状(j, i, 0, 1, true);  // 竖线（右侧）
                    //        this.添加线条形状(j, i, 1, 0, true);  // 横线（底部）
                    //    }
                    //}
                }
            }

            return this._报表;
        }

        public 形状 移除形状(IShape shape)
        {
            var _形状集 = 形状集;
            if (_形状集 == null || _形状集.形状集体 == null || _形状集.形状集体.Count <= 0 || shape == null) return null;
            if (_形状集.形状集体.Contains(shape) == false) return null;

            _形状集.形状集体.Remove(shape);
            return new 形状(shape);
        }

        public 形状 移除形状(int position)
        {
            var _形状集 = 形状集;
            if (_形状集.形状集体 == null || _形状集.形状集体 == null || _形状集.形状集体.Count <= 00) return null;
            if (position < 0 || position >= _形状集.形状集体.Count) return null;

            var shape = new 形状(_形状集.形状集体[position]);
            _形状集.形状集体.Remove(_形状集.形状集体[position]);
            return shape;
        }

        public 形状 移除形状(形状 shape)
        {
            var _形状集 = 形状集;
            if (_形状集 == null || _形状集.形状集体 == null || _形状集.形状集体.Count <= 0 || shape == null || shape.形状体 == null) return null;
            if (_形状集.形状集体.Contains(shape.形状体) == false) return null;

            _形状集.形状集体.Remove(shape.形状体);
            return shape;
        }

        public 形状 添加形状(形状 shape)
        {
            if (_幻灯片体 == null || _幻灯片体.Shapes == null || shape == null)
            {
                return null;
            }

            var shapeSet = 形状集;
            if (shapeSet == null) return null;

            shapeSet.添加形状(shape);
            return shape;
        }

        public 形状 添加样式文本块(形状样式 style, string text)
        {
            if (style == null) return null;

            var rect = 添加矩形形状(style.X, style.Y, style.宽度, style.高度, style.报表坐标系);
            if (rect == null) return null;

            rect.形状体.Fill.SetColor(style.形状背景色);
            rect.形状体.Outline.Weight = style.形状边框宽;
            rect.形状体.Outline.SetHexColor(style.形状边框色);
            rect.形状体.Text = text;
            rect.形状体.TextBox.Paragraphs[0].Portions[0].Font.LatinName = style.形状字体;
            rect.形状体.TextBox.Paragraphs[0].Portions[0].Font.Size = style.形状字号;
            rect.形状体.TextBox.Paragraphs[0].Portions[0].Font.Color.Update(style.形状前景色);
            rect.形状体.TextBox.Paragraphs[0].Portions[0].Font.IsBold = style.形状加粗;
            rect.形状体.TextBox.Paragraphs[0].Portions[0].Font.IsItalic = style.形状倾斜;
            rect.形状体.TextBox.Paragraphs[0].Portions[0].Font.Underline = 形状下划线.取形状下划线(style.形状下划线类型).形状下划线体;

            return rect;
        }

        public 形状 添加线条形状(int startPointX, int startPointY, int endOffsetX, int endOffsetY, bool asReport = false)
        {
            if (_幻灯片体 == null || _幻灯片体.Shapes == null)
            {
                return null;
            }

            var shapeSet = 形状集;
            if (shapeSet == null) return null;

            if (asReport && _报表 != null)
            {
                var hLength = _报表.单位行高;
                var wLength = _报表.单位列宽;

                shapeSet.添加线条形状(_报表.左边距 + startPointX * wLength, _报表.上边距 + startPointY * hLength, endOffsetX * wLength, endOffsetY * hLength);
            }
            else
            {
                shapeSet.添加线条形状(startPointX, startPointY, endOffsetX, endOffsetY);
            }

            return new 形状(shapeSet.形状集体.Last());
        }

        public 形状 添加矩形形状(int x, int y, int width, int height, bool asReport = false)
        {
            if (_幻灯片体 == null || _幻灯片体.Shapes == null)
            {
                return null;
            }

            var shapeSet = 形状集;
            if (shapeSet == null) return null;

            if (asReport && _报表 != null)
            {
                var hLength = _报表.单位行高;
                var wLength = _报表.单位列宽;

                shapeSet.添加矩形形状(_报表.左边距 + x * wLength, _报表.上边距 + y * hLength, width * wLength, height * hLength);
            }
            else
            {
                shapeSet.添加矩形形状(x, y, width, height);
            }

            return new 形状(shapeSet.形状集体.Last());
        }

        public 形状 添加文本块(int x, int y, int width, int height, string text, bool asReport = false,
                               string foreColor = "000000", string backColor = "FFFFFF",
                               string fontEnName = "simsun", decimal fontSize = 11,
                               bool isBold = false, bool isItalic = false, 形状下划线类型 underLineType = 形状下划线类型.形状无下划线,
                               decimal borderWeight = 0, string borderColor = "000000")
        {
            var rect = 添加矩形形状(x, y, width, height, asReport);
            if (rect == null) return null;

            rect.形状体.Fill.SetColor(backColor);
            rect.形状体.Outline.Weight = borderWeight;
            rect.形状体.Outline.SetHexColor(borderColor);
            rect.形状体.TextBox.Text = text;
            rect.形状体.TextBox.Paragraphs[0].Portions[0].Font.LatinName = fontEnName;
            rect.形状体.TextBox.Paragraphs[0].Portions[0].Font.Size = fontSize;
            rect.形状体.TextBox.Paragraphs[0].Portions[0].Font.Color.Update(foreColor);
            rect.形状体.TextBox.Paragraphs[0].Portions[0].Font.IsBold = isBold;
            rect.形状体.TextBox.Paragraphs[0].Portions[0].Font.IsItalic = isItalic;
            rect.形状体.TextBox.Paragraphs[0].Portions[0].Font.Underline = 形状下划线.取形状下划线(underLineType).形状下划线体;
            return rect;
        }

        public 形状 添加声音形状(int x, int y, string path, bool asReport = false)
        {
            if (_幻灯片体 == null || _幻灯片体.Shapes == null)
            {
                return null;
            }

            var shapeSet = 形状集;
            if (shapeSet == null) return null;

            if (asReport && _报表 != null)
            {
                var hLength = _报表.单位行高;
                var wLength = _报表.单位列宽;

                shapeSet.添加声音形状(_报表.左边距 + x * wLength, _报表.上边距 + y * hLength, path);
            }
            else
            {
                shapeSet.添加声音形状(x, y, path);
            }

            return new 形状(shapeSet.形状集体.Last());
        }

        public 形状 添加视频形状(int x, int y, string path, bool asReport = false)
        {
            if (_幻灯片体 == null || _幻灯片体.Shapes == null)
            {
                return null;
            }

            var shapeSet = 形状集;
            if (shapeSet == null) return null;

            if (asReport && _报表 != null)
            {
                var hLength = _报表.单位行高;
                var wLength = _报表.单位列宽;

                shapeSet.添加视频形状(_报表.左边距 + x * wLength, _报表.上边距 + y * hLength, path);
            }
            else
            {
                shapeSet.添加视频形状(x, y, path);
            }
            return new 形状(shapeSet.形状集体.Last());
        }

        public 形状 添加图像形状(int x, int y, int width, int height, string path, bool asReport = false)
        {
            if (_幻灯片体 == null || _幻灯片体.Shapes == null)
            {
                return null;
            }

            var shapeSet = 形状集;
            if (shapeSet == null) return null;

            shapeSet.添加图像形状(x, y, width, height, path, asReport);

            if (asReport && _报表 != null)
            {
                IPicture picture = shapeSet.形状集体.OfType<IPicture>().Last();

                var hLength = _报表.单位行高;
                var wLength = _报表.单位列宽;
                picture.X = _报表.左边距 + x * wLength;
                picture.Y = _报表.上边距 + y * hLength;
                picture.Width = width * wLength;
                picture.Height = height * hLength;
            }

            return new 形状(shapeSet.形状集体.Last());
        }

        public 形状 添加圆角矩形形状(int x, int y, int width, int height, bool asReport = false)
        {
            if (_幻灯片体 == null || _幻灯片体.Shapes == null)
            {
                return null;
            }

            var shapeSet = 形状集;
            if (shapeSet == null) return null;

            if (asReport && _报表 != null)
            {
                var hLength = _报表.单位行高;
                var wLength = _报表.单位列宽;

                shapeSet.添加圆角矩形形状(_报表.左边距 + x * wLength, _报表.上边距 + y * hLength, width * wLength, height * hLength);
            }
            else
            {
                shapeSet.添加圆角矩形形状(x, y, width, height);
            }
            return new 形状(shapeSet.形状集体.Last());
        }

        public 表格形状 添加表格形状(int x, int y, int width, int height, int columnsCount, int rowsCount, bool asReport = false)
        {
            if (_幻灯片体 == null || _幻灯片体.Shapes == null)
            {
                return null;
            }

            var shapeSet = 形状集;
            if (shapeSet == null) return null;

            if (asReport && _报表 != null)
            {
                var hLength = _报表.单位行高;
                var wLength = _报表.单位列宽;

                shapeSet.添加表格形状(_报表.左边距 + x * wLength, _报表.上边距 + y * hLength, width * wLength, height * hLength, columnsCount, rowsCount);
            }
            else
            {
                shapeSet.添加表格形状(x, y, width, height, columnsCount, rowsCount);
            }

            return new 表格形状((ITable)shapeSet.形状集体.Last());
        }

        public 幻灯片 替换形状框中文本(string newText)
        {
            if (_幻灯片体 == null) return this;

            var textFrames = _幻灯片体.TextFrames();

            foreach (var textFrame in textFrames)
            {
                textFrame.Text = newText;
            }
            return this;
        }

        public 幻灯片 插入二维文字表(string tableLines, int x, int y, int width, int height, bool asReport = false)
        {
            var txtTable = new 文字表(tableLines);

            表格形状 table;
            if (txtTable.文字表标题行 != null && string.IsNullOrWhiteSpace(txtTable.文字表标题行.文字表行标题文本) == false)
            {
                var columnsCount = txtTable.最大单元格数;
                table = this.添加表格形状(x, y, width, height, columnsCount, txtTable.文字表实际行数, asReport);
                var captionCell = table.取单元格形状(0, 0);
                captionCell.置单元格形状文本(txtTable.文字表标题文本);
                foreach (var p in captionCell.单元格形状体.TextBox.Paragraphs)
                {
                    p.HorizontalAlignment = TextHorizontalAlignment.Center;
                    foreach (var pt in p.Portions)
                    {
                        pt.Font.Size = 24;
                    }
                }
                table.表格体.MergeCells(captionCell.单元格形状体, table.取单元格形状(0, columnsCount - 1).单元格形状体);

                var headerRowsCount = 0;

                if (txtTable.文字表头行集 != null && txtTable.文字表头行集.Count > 0)
                {
                    headerRowsCount = txtTable.文字表头行集.Count;

                    for (int i = 0; i < txtTable.文字表头行集.Count; i++)
                    {
                        var tRow = txtTable.文字表头行集[i];
                        var hRow = table.取表格行形状(i);
                        for (int j = 0; j < tRow.行内实单元格数; j++)
                        {
                            var cell = table.取单元格形状(i + 1, j)
                                 .置单元格形状文本(tRow.文字表单元格集[j].文字表单元格文本);

                            cell.单元格形状体.TextBox.VerticalAlignment = TextVerticalAlignment.Middle;

                            foreach (var p in cell.单元格形状体.TextBox.Paragraphs)
                            {
                                p.HorizontalAlignment = TextHorizontalAlignment.Center;
                                foreach(var pt in p.Portions)
                                {
                                    pt.Font.Size = 24;
                                }
                            }
                        }
                    }
                }

                if (txtTable.文字表体行集 != null && txtTable.文字表体行集.Count > 0)
                {
                    for (int i = 0; i < txtTable.文字表体行集.Count; i++)
                    {
                        var tRow = txtTable.文字表体行集[i];
                        var hRow = table.取表格行形状(i + headerRowsCount);
                        for (int j = 0; j < tRow.行内实单元格数; j++)
                        {
                            var cell = table.取单元格形状(i + headerRowsCount + 1, j)
                                .置单元格形状文本(tRow.文字表单元格集[j].文字表单元格文本);

                            cell.单元格形状体.TextBox.VerticalAlignment = TextVerticalAlignment.Middle;

                            foreach (var p in cell.单元格形状体.TextBox.Paragraphs)
                            {
                                p.HorizontalAlignment = TextHorizontalAlignment.Center;
                                foreach (var pt in p.Portions)
                                {
                                    pt.Font.Size = 24;
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                var columnsCount = txtTable.最大单元格数;
                table = this.添加表格形状(x, y, width, height, columnsCount, txtTable.文字表实际行数, asReport);
                var captionCell = table.取单元格形状(0, 0);
                captionCell.置单元格形状文本(txtTable.文字表标题文本);

                var headerRowsCount = 0;

                if (txtTable.文字表头行集 != null && txtTable.文字表头行集.Count > 0)
                {
                    headerRowsCount = txtTable.文字表头行集.Count;

                    for (int i = 0; i < txtTable.文字表头行集.Count; i++)
                    {
                        var tRow = txtTable.文字表头行集[i];
                        var hRow = table.取表格行形状(i);
                        for (int j = 0; j < tRow.行内实单元格数; j++)
                        {
                            var cell = table.取单元格形状(i, j)
                                .置单元格形状文本(tRow.文字表单元格集[j].文字表单元格文本);

                            foreach (var p in cell.单元格形状体.TextBox.Paragraphs)
                            {
                                p.HorizontalAlignment = TextHorizontalAlignment.Center;
                            }
                        }
                    }
                }

                if (txtTable.文字表体行集 != null && txtTable.文字表体行集.Count > 0)
                {
                    for (int i = 0; i < txtTable.文字表体行集.Count; i++)
                    {
                        var tRow = txtTable.文字表体行集[i];
                        var hRow = table.取表格行形状(i + headerRowsCount);
                        for (int j = 0; j < tRow.行内实单元格数; j++)
                        {
                            var cell = table.取单元格形状(i + headerRowsCount, j)

                                .置单元格形状文本(tRow.文字表单元格集[j].文字表单元格文本);

                            foreach (var p in cell.单元格形状体.TextBox.Paragraphs)
                            {
                                p.HorizontalAlignment = TextHorizontalAlignment.Center;
                            }
                        }
                    }
                }
            }



            return this;
        }
    }

    public class 幻灯片集
    {
        public 幻灯片集(ISlides slides, 演示文稿管理器 masterPreManager)
        {
            _幻灯片集体 = slides;
            _主文稿 = masterPreManager;
        }

        private 演示文稿管理器 _主文稿;

        public 演示文稿管理器 主文稿
        {
            get { return _主文稿; }
        }

        private ISlides _幻灯片集体;

        public ISlides 幻灯片集体
        {
            get { return _幻灯片集体; }
        }

        public 幻灯片 首幻灯片
        {
            get
            {
                if (_幻灯片集体 == null || _幻灯片集体.Count <= 0) return null;

                return new 幻灯片(_幻灯片集体.First<ISlide>(), _主文稿);
            }
        }

        public 幻灯片 尾幻灯片
        {
            get
            {
                if (_幻灯片集体 == null || _幻灯片集体.Count <= 0) return null;

                return new 幻灯片(_幻灯片集体.Last<ISlide>(), _主文稿);
            }
        }

        public int 幻灯片数量
        {
            get
            {
                if (_幻灯片集体 == null) return 0;

                return _幻灯片集体.Count;
            }
        }

        public 幻灯片 添加幻灯片(幻灯片 slide)
        {
            if (_幻灯片集体 == null) return null;

            _幻灯片集体.Add(slide.幻灯片体);
            return slide;
        }

        public 幻灯片 添加幻灯片(幻灯片布局 layout = 幻灯片布局.空白布局)
        {
            if (_幻灯片集体 == null) return null;

            switch (layout)
            {
                case 幻灯片布局.空白布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.Blank);
                    break;
                case 幻灯片布局.图表布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.Chart);
                    break;
                case 幻灯片布局.图表和文本布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.ChartAndText);
                    break;
                case 幻灯片布局.剪贴画和文本布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.ClipArtAndText);
                    break;
                case 幻灯片布局.剪贴画与竖排文本布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.ClipArtAndVerticalText);
                    break;
                case 幻灯片布局.自定义布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.Custom);
                    break;
                case 幻灯片布局.示意图布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.Diagram);
                    break;
                case 幻灯片布局.四对象布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.FourObjects);
                    break;
                case 幻灯片布局.多媒体与文本布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.MediaAndText);
                    break;
                case 幻灯片布局.对象布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.Object);
                    break;
                case 幻灯片布局.单对象和双对象布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.ObjectAndTwoObjects);
                    break;
                case 幻灯片布局.对象和文本布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.ObjectAndText);
                    break;
                case 幻灯片布局.仅对象布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.ObjectOnly);
                    break;
                case 幻灯片布局.对象在文本上布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.ObjectOverText);
                    break;
                case 幻灯片布局.对象文本布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.ObjectText);
                    break;
                case 幻灯片布局.图形与标题布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.PictureAndCaption);
                    break;
                case 幻灯片布局.区块头布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.SectionHeader);
                    break;
                case 幻灯片布局.表布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.Table);
                    break;
                case 幻灯片布局.标题布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.Title);
                    break;
                case 幻灯片布局.仅标题布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TitleOnly);
                    break;
                case 幻灯片布局.双列文本布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TwoColumnText);
                    break;
                case 幻灯片布局.双对象布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TwoObjects);
                    break;
                case 幻灯片布局.双对象和单对象布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TwoObjectsAndObject);
                    break;
                case 幻灯片布局.双对象和文本布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TwoObjectsAndText);
                    break;
                case 幻灯片布局.双对象在文本上布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TwoObjectsOverText);
                    break;
                case 幻灯片布局.双文本和双对象布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TwoTextAndTwoObjects);
                    break;
                case 幻灯片布局.文本布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.Text);
                    break;
                case 幻灯片布局.文本和图表布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TextAndChart);
                    break;
                case 幻灯片布局.文本和剪贴画布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TextAndClipArt);
                    break;
                case 幻灯片布局.文本和多媒体布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TextAndMedia);
                    break;
                case 幻灯片布局.文本和对象布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TextAndObject);
                    break;
                case 幻灯片布局.文本和双对象布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TextAndTwoObjects);
                    break;
                case 幻灯片布局.文本在对象上布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.TextOverObject);
                    break;
                case 幻灯片布局.竖排标题和文本布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.VerticalTitleAndText);
                    break;
                case 幻灯片布局.竖排标题和文本在图表上布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.VerticalTitleAndTextOverChart);
                    break;
                case 幻灯片布局.竖排文本布局:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.VerticalText);
                    break;
                default:
                    _幻灯片集体.AddEmptySlide(SlideLayoutType.Blank);
                    break;
            }

            return new 幻灯片(_幻灯片集体.Last<ISlide>(), _主文稿);
        }

        public 幻灯片 插入幻灯片(int position, 幻灯片布局 layout)
        {
            var newSlide = 添加幻灯片(layout);
            移除幻灯片(_幻灯片集体.Count - 1);
            插入幻灯片(position, newSlide);
            return newSlide;
        }

        public 幻灯片 插入幻灯片(int position, 幻灯片 slide)
        {
            if (_幻灯片集体 == null) return null;

            _幻灯片集体.Insert(position, slide.幻灯片体);
            return slide;
        }

        public void 移除幻灯片(int position)
        {
            if (_幻灯片集体 == null || _幻灯片集体.Count <= 0) return;
            if (position < 0 || position >= _幻灯片集体.Count) return;

            _幻灯片集体.Remove(_幻灯片集体[position]);
        }

        public void 移除幻灯片(幻灯片 slide)
        {
            if (_幻灯片集体 == null || _幻灯片集体.Count <= 0) return;
            if (_幻灯片集体.Contains(slide.幻灯片体) == false) return;

            _幻灯片集体.Remove(slide.幻灯片体);
        }
    }

    public class 形状
    {
        public 形状(IShape shape)
        {
            _形状体 = shape;
        }

        private IShape _形状体;

        public IShape 形状体
        {
            get { return _形状体; }
        }

        public 文本框形状 文本框形状
        {
            get
            {
                if (_形状体 == null) return null;

                return new 文本框形状(_形状体.TextBox);
            }
        }

        public decimal 形状横坐标
        {
            get
            {
                if (_形状体 == null) return 0;
                return _形状体.X;
            }
            set { _形状体.X = value; }
        }

        public decimal 形状纵坐标
        {
            get { return _形状体.Y; }
            set { _形状体.Y = value; }
        }

        public decimal 形状宽度
        {
            get { return _形状体.Width; }
            set { _形状体.Width = value; }
        }

        public decimal 形状高度
        {
            get { return _形状体.Height; }
            set { _形状体.Height = value; }
        }

        public 形状 置形状文本(string text)
        {
            if (_形状体 == null) return this;

            if (string.IsNullOrWhiteSpace(text)) text = "";

            _形状体.TextBox.Text = text;
            return this;
        }

        public string 取形状文本()
        {
            if (_形状体 == null) return null;

            return _形状体.TextBox.Text;
        }

        public 形状 置形状背景色(string rgbText)
        {
            if (_形状体 == null || _形状体.HasFill == false) return this;

            if (string.IsNullOrWhiteSpace(rgbText)) rgbText = "FFFFFF";  // 默认白色

            _形状体.Fill.SetColor(rgbText.TrimStart(new char[] { '#' }));
            return this;
        }

        public 形状 置形状边框宽(decimal weight)
        {
            if (_形状体 == null) return this;

            if (weight < 0) weight = 0;
            _形状体.Outline.Weight = weight;
            return this;
        }

        public 形状 置形状边框宽度(decimal weight)
        {
            if (_形状体 == null) return this;

            if (weight < 0) weight = 0;
            _形状体.Outline.Weight = weight;
            return this;
        }

        public 形状 置形状边框色(string rgbText)
        {
            if (_形状体 == null || _形状体.HasOutline == false) return this;

            if (string.IsNullOrWhiteSpace(rgbText)) rgbText = "FFFFFF";  // 默认白色

            _形状体.Outline.SetHexColor(rgbText.TrimStart(new char[] { '#' }));
            return this;
        }

        public 形状类型 取形状类型()
        {
            if (_形状体 == null) return 形状类型.自动型;

            switch (_形状体.ShapeType)
            {
                case ShapeType.Audio: return 形状类型.音频型;
                case ShapeType.AutoShape: return 形状类型.自动型;
                case ShapeType.Chart: return 形状类型.图表型;
                case ShapeType.Group: return 形状类型.组合型;
                case ShapeType.Line: return 形状类型.线条型;
                case ShapeType.Picture: return 形状类型.图形型;
                case ShapeType.Table: return 形状类型.表格型;
                case ShapeType.Video: return 形状类型.视频型;
            }

            return 形状类型.自动型;
        }

        public bool 是否占位符
        {
            get
            {
                if (_形状体 == null) return false;

                return _形状体.IsPlaceholder;
            }
        }

        public 占位符类型 取占位符类型()
        {
            switch (_形状体.PlaceholderType)
            {
                case PlaceholderType.Content: return 占位符类型.内容占位符;
                case PlaceholderType.Text: return 占位符类型.文本占位符;
                case PlaceholderType.Picture: return 占位符类型.图形占位符;
                case PlaceholderType.Table: return 占位符类型.表占位符;
                case PlaceholderType.SmartArt: return 占位符类型.智能图表占位符;
                case PlaceholderType.Media: return 占位符类型.媒体占位符;
                case PlaceholderType.OnlineImage: return 占位符类型.在线图像占位符;
                case PlaceholderType.Title: return 占位符类型.标题占位符;
                case PlaceholderType.CenteredTitle: return 占位符类型.居中标题占位符;
                case PlaceholderType.SubTitle: return 占位符类型.副标题占位符;
                case PlaceholderType.DateAndTime: return 占位符类型.日期时间占位符;
                case PlaceholderType.SlideNumber: return 占位符类型.幻灯片编号占位符;
                case PlaceholderType.Footer: return 占位符类型.页脚占位符;
                case PlaceholderType.OleObject: return 占位符类型.Ole占位符;
                case PlaceholderType.Chart: return 占位符类型.图表占位符;
                case PlaceholderType.SlideImage: return 占位符类型.幻灯片图像占位符;
            }

            return 占位符类型.内容占位符;
        }

        public int? 取形状标识符()
        {
            if (_形状体 == null) return null;

            return _形状体.Id;
        }

        public string 自定义数据
        {
            get
            {
                if (_形状体 == null || _形状体.CustomData == null) return null;

                return _形状体.CustomData;
            }
        }

        public 形状文本自适应类型 自适应类型
        {
            get
            {
                if (_形状体 == null || _形状体.TextBox == null) return 形状文本自适应类型.无自适应;

                switch (_形状体.TextBox.AutofitType)
                {
                    case AutofitType.Shrink: return 形状文本自适应类型.收缩适应;
                    case AutofitType.Resize: return 形状文本自适应类型.重设尺寸适应;
                    default: return 形状文本自适应类型.无自适应;
                }
            }
            set
            {
                if (_形状体 == null || _形状体.TextBox == null) return;

                switch (value)
                {
                    case 形状文本自适应类型.收缩适应:
                        _形状体.TextBox.AutofitType = AutofitType.Shrink;
                        break;
                    case 形状文本自适应类型.重设尺寸适应:
                        _形状体.TextBox.AutofitType = AutofitType.Resize;
                        break;
                    default:
                        _形状体.TextBox.AutofitType = AutofitType.None;
                        break;
                }
            }
        }

        public 形状 置形状字体字号(decimal fontSize)
        {
            if (this._形状体 == null || this._形状体.TextBox == null ||
                this._形状体.TextBox.Paragraphs == null || this._形状体.TextBox.Paragraphs.Count <= 0) return this;

            foreach (var para in this._形状体.TextBox.Paragraphs)
            {
                var ports = para.Portions;

                if (ports == null || ports.Count <= 0) continue;

                foreach (var port in ports)
                {
                    port.Font.Size = fontSize;
                }
            }
            return this;
        }

        public 形状 置形状字体名(string fontName)
        {
            if (this._形状体 == null || this._形状体.TextBox == null ||
                this._形状体.TextBox.Paragraphs == null || this._形状体.TextBox.Paragraphs.Count <= 0) return this;

            foreach (var para in this._形状体.TextBox.Paragraphs)
            {
                var ports = para.Portions;
                if (ports == null || ports.Count <= 0) continue;

                foreach (var port in ports)
                {
                    port.Font.EastAsianName = fontName;
                    port.Font.LatinName = fontName;
                }
            }
            return this;
        }

        public 形状 置形状字体色彩(string hex)
        {
            if (this._形状体 == null || this._形状体.TextBox == null ||
                this._形状体.TextBox.Paragraphs == null || this._形状体.TextBox.Paragraphs.Count <= 0) return this;

            foreach (var para in this._形状体.TextBox.Paragraphs)
            {
                var ports = para.Portions;
                if (ports == null || ports.Count <= 0) continue;

                foreach (var port in ports)
                {
                    port.Font.Color.Update(hex);
                }
            }
            return this;
        }

        public 形状 置形状字体加粗(bool isbold)
        {
            if (this._形状体 == null || this._形状体.TextBox == null ||
                this._形状体.TextBox.Paragraphs == null || this._形状体.TextBox.Paragraphs.Count <= 0) return this;

            foreach (var para in this._形状体.TextBox.Paragraphs)
            {
                var ports = para.Portions;
                if (ports == null || ports.Count <= 0) continue;

                foreach (var port in ports)
                {
                    port.Font.IsBold = isbold;
                }
            }
            return this;
        }

        public 形状 置形状字体倾斜(bool isItalic)
        {
            if (this._形状体 == null || this._形状体.TextBox == null ||
                this._形状体.TextBox.Paragraphs == null || this._形状体.TextBox.Paragraphs.Count <= 0) return this;

            foreach (var para in this._形状体.TextBox.Paragraphs)
            {
                var ports = para.Portions;
                if (ports == null || ports.Count <= 0) continue;

                foreach (var port in ports)
                {
                    port.Font.IsItalic = isItalic;
                }
            }
            return this;
        }

        public 形状 置形状文本对齐(string align)
        {
            if (this.形状体 == null || this.形状体.TextBox == null) return this;

            switch (align.Trim().ToLower())
            {
                case "l":
                case "lt":
                case "lft":
                case "left":
                case "左":
                case "左齐":
                case "左对齐":
                    {
                        foreach (var p in this.形状体.TextBox.Paragraphs)
                        {
                            p.HorizontalAlignment = TextHorizontalAlignment.Left;
                        }
                        break;
                    }
                case "r":
                case "rt":
                case "rgt":
                case "right":
                case "右":
                case "右齐":
                case "右对齐":
                    {
                        foreach (var p in this.形状体.TextBox.Paragraphs)
                        {
                            p.HorizontalAlignment = TextHorizontalAlignment.Right;
                        }
                        break;
                    }
                case "c":
                case "ct":
                case "cnt":
                case "center":
                case "中":
                case "居中":
                case "中对齐":
                case "居中对齐":
                    {
                        foreach (var p in this.形状体.TextBox.Paragraphs)
                        {
                            p.HorizontalAlignment = TextHorizontalAlignment.Center;
                        }
                        break;
                    }
                //case "b":
                //case "j":
                //case "两侧":
                //case "两侧对齐":
                //case "两端对齐":
                //case "自适应":
                //case "自适应对齐":
                default:
                    {
                        foreach (var p in this.形状体.TextBox.Paragraphs)
                        {
                            p.HorizontalAlignment = TextHorizontalAlignment.Justify;
                        }
                        break;
                    }
            }

            return this;
        }
    }

    public class 表格形状 : 形状
    {
        public 表格形状(ITable table) : base(table)
        {
            _表格体 = table;
        }

        private ITable _表格体;

        public ITable 表格体
        {
            get { return _表格体; }
        }

        public int 表格形状行数
        {
            get
            {
                if (_表格体 == null) return 0;
                return _表格体.Rows.Count;
            }
        }

        public int 表格形状列数
        {
            get
            {
                if (_表格体 == null) return 0;
                return _表格体.Columns.Count;
            }
        }

        public 表格行形状 插入表格行形状(int position)
        {
            if (_表格体 == null) return null;

            _表格体.Rows.Add();
            var row = _表格体.Rows.Last<ITableRow>();
            return new 表格行形状(row);
        }

        public 表格行形状 取表格行形状(int position)
        {
            if (_表格体 == null) return null;
            if (position < 0 || position >= _表格体.Rows.Count) return null;

            var row = _表格体.Rows[position];
            return new 表格行形状(row);
        }

        public 表格行形状 删除表格行形状(int position)
        {
            if (_表格体 == null) return null;
            if (position < 0 || position >= _表格体.Rows.Count) return null;

            var row = _表格体.Rows[position];
            return new 表格行形状(row);
        }

        public 表格行形状 删除表格行形状(表格行形状 destRow)
        {
            if (_表格体 == null) return null;
            if (_表格体.Rows.Contains(destRow.表格行形状体) == false) return null;

            _表格体.Rows.Remove(destRow.表格行形状体);
            return destRow;
        }

        public 单元格形状 取单元格形状(int rowIndex, int colIndex)
        {
            return new 单元格形状(_表格体[rowIndex, colIndex]);
        }

        public 单元格形状 合并单元格形状(int startRow, int startColumn, int endRow, int endColumn)
        {
            if (_表格体 == null) return null;

            var left = Math.Min(startColumn, endColumn);
            var top = Math.Min(startRow, endRow);
            var ltCell = 取单元格形状(top, left);
            var rbCell = 取单元格形状(Math.Max(startRow, endRow), Math.Max(startColumn, endColumn));
            _表格体.MergeCells(ltCell.单元格形状体, rbCell.单元格形状体);
            return 取单元格形状(top, left);
        }

        public 表格形状 置表格形状列宽(int colIndex, int width)
        {
            if (_表格体 == null) return this;
            if (colIndex < 0 || colIndex >= _表格体.Columns.Count) return this;

            _表格体.Columns[colIndex].Width = width;
            return this;
        }

        public 表格形状 置表格形状边框(string rgbColor = "000000", decimal weight = 1)
        {
            if (_表格体 == null) return this;

            if (weight <= 0)
            {
                _表格体.Outline.SetNoOutline();
                return this;
            }

            if (string.IsNullOrWhiteSpace(rgbColor))
            {
                rgbColor = "000000";
            }
            else
            {
                rgbColor = rgbColor.Trim(new char[] { ' ', '　', '\t', '\r', '\n' });
                if (rgbColor.Length != 6)
                {
                    rgbColor = "000000";
                }
            }

            _表格体.Outline.Weight = weight;
            _表格体.Outline.SetHexColor(rgbColor);
            return this;
        }
    }

    public class 表格行形状
    {
        public 表格行形状(ITableRow row)
        {
            _表格行形状体 = row;
        }

        private ITableRow _表格行形状体;

        public ITableRow 表格行形状体
        {
            get { return _表格行形状体; }
        }

        public int 单元格形状数量
        {
            get
            {
                if (_表格行形状体 == null) return 0;

                return _表格行形状体.Cells.Count;
            }
        }

        public int 表格行形状高度
        {
            get
            {
                if (_表格行形状体 == null) return 0;

                return _表格行形状体.Height;
            }
            set
            {
                if (_表格行形状体 == null) return;

                _表格行形状体.Height = value;
            }
        }
    }

    public class 单元格形状
    {
        public 单元格形状(ITableCell cell)
        {
            _单元格形状体 = cell;
        }

        private ITableCell _单元格形状体;

        public ITableCell 单元格形状体
        {
            get { return _单元格形状体; }
        }

        public 文本框形状 文本框形状
        {
            get
            {
                if (_单元格形状体 == null) return null;

                return new 文本框形状(_单元格形状体.TextBox);
            }
        }

        public 单元格形状 置单元格形状文本(string text)
        {
            if (_单元格形状体 == null) return this;

            _单元格形状体.TextBox.Text = string.IsNullOrWhiteSpace(text) ? "" : text;

            return this;
        }
    }

    public enum 形状文本自适应类型
    {
        无自适应 = AutofitType.None,
        收缩适应 = AutofitType.Shrink,
        重设尺寸适应 = AutofitType.Resize,
    }

    public enum 占位符类型
    {
        内容占位符 = PlaceholderType.Content,
        文本占位符 = PlaceholderType.Text,
        图形占位符 = PlaceholderType.Picture,
        表占位符 = PlaceholderType.Table,
        智能图表占位符 = PlaceholderType.SmartArt,
        媒体占位符 = PlaceholderType.Media,
        在线图像占位符 = PlaceholderType.OnlineImage,
        标题占位符 = PlaceholderType.Title,
        居中标题占位符 = PlaceholderType.CenteredTitle,
        副标题占位符 = PlaceholderType.SubTitle,
        日期时间占位符 = PlaceholderType.DateAndTime,
        幻灯片编号占位符 = PlaceholderType.SlideNumber,
        页脚占位符 = PlaceholderType.Footer,
        Ole占位符 = PlaceholderType.OleObject,
        图表占位符 = PlaceholderType.Chart,
        幻灯片图像占位符 = PlaceholderType.SlideImage,
    }

    public enum 形状类型
    {
        音频型 = ShapeType.Audio,
        自动型 = ShapeType.AutoShape,
        图表型 = ShapeType.Chart,
        线条型 = ShapeType.Line,
        组合型 = ShapeType.Group,
        图形型 = ShapeType.Picture,
        视频型 = ShapeType.Video,
        表格型 = ShapeType.Table,
    }

    public class 形状集
    {
        public 形状集(ISlideShapes slideShapes)
        {
            _形状集体 = slideShapes;
        }

        private ISlideShapes _形状集体;

        public ISlideShapes 形状集体
        {
            get { return _形状集体; }
        }

        public 形状 首形状
        {
            get
            {
                if (_形状集体 == null || _形状集体.Count <= 0) return null;

                return new 形状(_形状集体.First());
            }
        }

        public 形状 尾形状
        {
            get
            {
                if (_形状集体 == null || _形状集体.Count <= 0) return null;

                return new 形状(_形状集体.Last());
            }
        }

        public 形状 按名称取形状(string name)
        {
            if (_形状集体 == null || _形状集体.Count <= 0) return null;

            return new 形状(_形状集体.GetByName<IShape>(name));
        }

        public 图形形状 按名称取图像形状(string name)
        {
            if (_形状集体 == null || _形状集体.Count <= 0) return null;

            return new 图形形状(_形状集体.GetByName<IPicture>(name));
        }

        public int 形状个数
        {
            get
            {
                if (_形状集体 == null || _形状集体.Count <= 0) return 0;

                return _形状集体.Count;
            }
        }

        public 形状 移除形状(IShape shape)
        {
            if (_形状集体 == null || _形状集体.Count <= 0 || shape == null) return null;

            if (_形状集体.Contains(shape) == false) return null;

            _形状集体.Remove(shape);
            return new 形状(shape);
        }

        public 形状 移除形状(int position)
        {
            if (_形状集体 == null || _形状集体.Count <= 0) return null;
            if (position < 0 || position >= _形状集体.Count) return null;

            var shape = new 形状(_形状集体[position]);
            _形状集体.Remove(_形状集体[position]);
            return shape;
        }

        public 形状 移除形状(形状 shape)
        {
            if (_形状集体 == null || _形状集体.Count <= 0 || shape == null || shape.形状体 == null) return null;
            if (_形状集体.Contains(shape.形状体) == false) return null;

            _形状集体.Remove(shape.形状体);
            return shape;
        }

        public 形状 添加形状(形状 shape)
        {
            if (_形状集体 == null || shape == null) return null;

            _形状集体.Add(shape.形状体);
            return shape;
        }

        public 形状 添加线条形状(int startPointX, int startPointY, int endOffsetX, int endOffsetY, bool byOffset = true)
        {
            if (_形状集体 == null) return null;

            // ShapeCrawler 有 bug: 当 endPointX 为 0 时，它会失效；而且 AddLine 的后两个参数命名也不准确。
            if (byOffset)
            {
                if (endOffsetX == 0) endOffsetX += startPointX;
            }

            _形状集体.AddLine(startPointX, startPointY, endOffsetX, endOffsetY);
            return new 形状(_形状集体.Last());
        }

        public 形状 添加矩形形状(int x, int y, int width, int height)
        {
            if (_形状集体 == null) return null;

            _形状集体.AddShape(x, y, width, height, Geometry.Rectangle);
            return new 形状(_形状集体.Last());
        }

        public 形状 添加声音形状(int x, int y, string path)
        {
            if (_形状集体 == null) return null;

            using (var fm = new FileStream(path, FileMode.Open))
            {
                _形状集体.AddAudio(x, y, fm);
            }
            return new 形状(_形状集体.Last());
        }

        public 形状 添加视频形状(int x, int y, string path)
        {
            if (_形状集体 == null) return null;

            using (var fm = new FileStream(path, FileMode.Open))
            {
                _形状集体.AddVideo(x, y, fm);
            }
            return new 形状(_形状集体.Last());
        }

        public 形状 添加图像形状(int x, int y, int width, int height, string path, bool asReport = false)
        {
            if (_形状集体 == null) return null;

            using (var fm = new FileStream(path, FileMode.Open))
            {
                _形状集体.AddPicture(fm);

                IPicture picture = _形状集体.OfType<IPicture>().Last();

                picture.X = x;
                picture.Y = y;
                picture.Width = width; // pixels
                picture.Height = height;
            }

            return new 形状(_形状集体.Last());
        }

        public 形状 添加圆角矩形形状(int x, int y, int width, int height)
        {
            if (_形状集体 == null) return null;

            _形状集体.AddShape(x, y, width, height, Geometry.RoundedRectangle);
            return new 形状(_形状集体.Last());
        }

        public 表格形状 添加表格形状(int x, int y, int width, int height, int columnsCount, int rowsCount)
        {
            if (_形状集体 == null) return null;

            _形状集体.AddTable(x, y, columnsCount, rowsCount);
            var table = (ITable)_形状集体.Last();

            table.Width = width;   // 已知 ShapeCrawler 0.60 版本这两个属性无效。2025.2.6
            table.Height = height; // 等新版本解决此问题。

            return new 表格形状(table);
        }
    }

    public class 文本框形状
    {
        public 文本框形状(ITextBox tFrame)
        {
            _形状文本框体 = tFrame;
        }

        private ITextBox _形状文本框体;

        public ITextBox 形状文本框体
        {
            get { return _形状文本框体; }
        }

        public 形状段落 首形状段落
        {
            get
            {
                if (_形状文本框体 == null || _形状文本框体.Paragraphs.Count <= 0) return null;

                return new 形状段落(_形状文本框体.Paragraphs.First<IParagraph>());
            }
        }

        public 形状段落 尾形状段落
        {
            get
            {
                if (_形状文本框体 == null || _形状文本框体.Paragraphs.Count <= 0) return null;

                return new 形状段落(_形状文本框体.Paragraphs.Last<IParagraph>());
            }
        }

        public 形状片段 首形状片段
        {
            get
            {
                var _首形状段落 = 首形状段落;
                if (_首形状段落 == null || _首形状段落.片段个数 <= 0) return null;

                return _首形状段落.首形状片段;
            }
        }

        public 形状片段 尾形状片段
        {
            get
            {
                var _尾形状段落 = 尾形状段落;
                if (_尾形状段落 == null || _尾形状段落.片段个数 <= 0) return null;

                return _尾形状段落.尾形状片段;
            }
        }

        public 文本框形状 置形状边距(decimal leftMargin, decimal topMargin, decimal rightMargin, decimal bottomMargin)
        {
            this.左边距 = leftMargin;
            this.上边距 = topMargin;
            this.右边距 = rightMargin;
            this.下边距 = bottomMargin;
            return this;
        }

        public decimal 左边距
        {
            get { return _形状文本框体.LeftMargin; }
            set { _形状文本框体.LeftMargin = value; }
        }

        public decimal 上边距
        {
            get { return _形状文本框体.TopMargin; }
            set { _形状文本框体.TopMargin = value; }
        }
        public decimal 顶边距
        {
            get { return _形状文本框体.TopMargin; }
            set { _形状文本框体.TopMargin = value; }
        }

        public decimal 右边距
        {
            get { return _形状文本框体.RightMargin; }
            set { _形状文本框体.RightMargin = value; }
        }

        public decimal 下边距
        {
            get { return _形状文本框体.BottomMargin; }
            set { _形状文本框体.BottomMargin = value; }
        }
        public decimal 底边距
        {
            get { return _形状文本框体.BottomMargin; }
            set { _形状文本框体.BottomMargin = value; }
        }

        public 形状文本自适应类型 自适应类型
        {
            get
            {
                if (_形状文本框体 == null) return 形状文本自适应类型.无自适应;

                switch (_形状文本框体.AutofitType)
                {
                    case AutofitType.Shrink: return 形状文本自适应类型.收缩适应;
                    case AutofitType.Resize: return 形状文本自适应类型.重设尺寸适应;
                    default: return 形状文本自适应类型.无自适应;
                }
            }
            set
            {
                if (_形状文本框体 == null) return;

                switch (value)
                {
                    case 形状文本自适应类型.收缩适应:
                        _形状文本框体.AutofitType = AutofitType.Shrink;
                        break;
                    case 形状文本自适应类型.重设尺寸适应:
                        _形状文本框体.AutofitType = AutofitType.Resize;
                        break;
                    default:
                        _形状文本框体.AutofitType = AutofitType.None;
                        break;
                }
            }
        }

        public 文本框形状 替换形状框中文本(string newText)
        {
            if (_形状文本框体 == null) return this;

            _形状文本框体.Text = newText;
            return this;
        }

        public string 形状文本
        {
            get
            {
                if (_形状文本框体 == null) return null;

                return _形状文本框体.Text;
            }
            set
            {
                if (_形状文本框体 == null) return;

                _形状文本框体.Text = value;
            }
        }
    }

    public class 形状段落
    {
        public 形状段落(IParagraph para)
        {
            _形状段落体 = para;
        }

        private IParagraph _形状段落体;

        public IParagraph 形状段落体
        {
            get { return _形状段落体; }
        }

        public 形状段落 置文本(string text)
        {
            if (_形状段落体 == null) return this;

            if (string.IsNullOrWhiteSpace(text)) { text = ""; }

            _形状段落体.Text = text;
            return this;
        }

        public int 片段个数
        {
            get
            {
                if (_形状段落体 == null) return 0;

                return _形状段落体.Portions.Count;
            }
        }

        public 形状片段 首形状片段
        {
            get
            {
                if (_形状段落体 == null || _形状段落体.Portions.Count <= 0) return null;

                return new 形状片段(_形状段落体.Portions.First<IParagraphPortion>());
            }
        }

        public 形状片段 尾形状片段
        {
            get
            {
                if (_形状段落体 == null || _形状段落体.Portions.Count <= 0) return null;

                return new 形状片段(_形状段落体.Portions.Last<IParagraphPortion>());
            }
        }

        public 形状对齐 形状对齐
        {
            get
            {
                if (_形状段落体 == null) return 形状对齐.形状左对齐;

                switch (_形状段落体.HorizontalAlignment)
                {
                    case TextHorizontalAlignment.Center: return 形状对齐.形状居中对齐;
                    case TextHorizontalAlignment.Right: return 形状对齐.形状右对齐;
                    case TextHorizontalAlignment.Justify: return 形状对齐.形状两端对齐;
                    default:
                        return 形状对齐.形状左对齐;
                }
            }
            set
            {
                if (_形状段落体 == null) return;

                switch (value)
                {
                    case 形状对齐.形状右对齐:
                        _形状段落体.HorizontalAlignment = TextHorizontalAlignment.Right;
                        break;
                    case 形状对齐.形状居中对齐:
                        _形状段落体.HorizontalAlignment = TextHorizontalAlignment.Center;
                        break;
                    case 形状对齐.形状两端对齐:
                        _形状段落体.HorizontalAlignment = TextHorizontalAlignment.Justify;
                        break;
                    default:
                        _形状段落体.HorizontalAlignment = TextHorizontalAlignment.Left;
                        break;
                }
            }
        }

        public int 形状缩进级别
        {
            get
            {
                if (_形状段落体 == null) return 0;
                return _形状段落体.IndentLevel;
            }
            set
            {
                if (_形状段落体 == null) return;
                _形状段落体.IndentLevel = value;
            }
        }
    }

    public enum 形状对齐
    {
        形状左对齐,
        形状右对齐,
        形状居中对齐,
        形状两端对齐,
    }

    public class 形状段落集
    {
        public 形状段落集(IParagraphs paras)
        {
            _形状段落集体 = paras;
        }

        private IParagraphs _形状段落集体;

        public IParagraphs 形状段落集体
        {
            get { return _形状段落集体; }
        }

        public 形状段落 首形状段落
        {
            get
            {
                if (_形状段落集体 == null || _形状段落集体.Count <= 0) return null;

                return new 形状段落(_形状段落集体.First<IParagraph>());
            }
        }
        public 形状段落 尾形状段落
        {
            get
            {
                if (_形状段落集体 == null || _形状段落集体.Count <= 0) return null;

                return new 形状段落(_形状段落集体.Last<IParagraph>());
            }
        }
    }

    public class 形状片段
    {
        public 形状片段(IParagraphPortion paraPortion)
        {
            _形状片段体 = paraPortion;
        }

        private IParagraphPortion _形状片段体;

        public IParagraphPortion 形状片段体
        {
            get { return _形状片段体; }
        }

        public 形状片段 置形状片段字体(string fontEnName, decimal fontSize, bool bold, bool italic, 形状下划线类型 type, string rgbHex, int offset)
        {
            if (_形状片段体 == null || _形状片段体.Font == null) return this;

            var _font = new 形状字体(_形状片段体.Font);
            _font.置形状字体英文名(fontEnName);
            _font.置形状字号(fontSize);
            _font.形状字体是否加粗 = bold;
            _font.形状字体是否倾斜 = italic;
            _font.置形状字体下划线类型(type);
            _font.置形状字体色彩标记(rgbHex);
            _font.置形状字体偏移量(offset);

            return this;
        }

        public 形状片段 置形状片段字体英文名(string fontEnName)
        {
            if (_形状片段体 == null || _形状片段体.Font == null) return this;

            var _ = new 形状字体(_形状片段体.Font);
            _.置形状字体英文名(fontEnName);

            return this;
        }

        public 形状片段 置形状片段字体中文名(string fontCnName)
        {
            if (_形状片段体 == null || _形状片段体.Font == null) return this;

            var _ = new 形状字体(_形状片段体.Font);
            _.置形状字体中文名(fontCnName);
            return this;
        }

        public 形状片段 置形状片段字号(decimal fontSize)
        {
            if (_形状片段体 == null || _形状片段体.Font == null) return this;

            var _ = new 形状字体(_形状片段体.Font);
            _.置形状字号(fontSize);
            return this;
        }
        public 形状片段 置形状片段加粗(bool bold)
        {
            if (_形状片段体 == null || _形状片段体.Font == null) return this;

            var _ = new 形状字体(_形状片段体.Font);
            _.形状字体是否加粗 = bold;
            return this;
        }

        public 形状片段 置形状片段倾斜(bool italic)
        {
            if (_形状片段体 == null || _形状片段体.Font == null) return this;

            var _ = new 形状字体(_形状片段体.Font);
            _.形状字体是否倾斜 = italic;
            return this;
        }
        public 形状片段 置形状片段下划线类型(形状下划线类型 type)
        {
            if (_形状片段体 == null || _形状片段体.Font == null) return this;

            var _ = new 形状字体(_形状片段体.Font);
            _.置形状字体下划线类型(type);
            return this;
        }
        public 形状片段 置形状片段色彩(string rgbHex)
        {
            if (_形状片段体 == null || _形状片段体.Font == null) return this;

            var _ = new 形状字体(_形状片段体.Font);
            _.置形状字体色彩标记(rgbHex);
            return this;
        }

        /// <summary>
        /// 用以决定上下标位置。
        /// </summary>
        /// <param name="offset">上下偏移量。</param>
        /// <returns></returns>
        public 形状片段 置形状片段字体偏移量(int offset)
        {
            if (_形状片段体 == null || _形状片段体.Font == null) return this;

            var _ = new 形状字体(_形状片段体.Font);
            _.置形状字体偏移量(offset);
            return this;
        }

        /// <summary>
        /// 按 RGB 字符串表示的色彩设置为文本高亮色彩。
        /// </summary>
        /// <param name="rgb">不加 # 标记。</param>
        /// <returns></returns>
        public 形状片段 置形状片段高亮色(string rgb)
        {
            if (_形状片段体 == null) return this;

            _形状片段体.TextHighlightColor = ShapeCrawler.Color.FromHex(rgb);
            return this;
        }
    }

    public class 形状片段集
    {
        public 形状片段集(IParagraphPortions paraPortions)
        {
            _形状片段集体 = paraPortions;
        }

        private IParagraphPortions _形状片段集体;

        public IParagraphPortions 形状片段集体
        {
            get { return _形状片段集体; }
        }

        public 形状片段 首形状片段
        {
            get
            {
                if (_形状片段集体 == null || _形状片段集体.Count <= 0) return null;

                return new 形状片段(_形状片段集体.First<IParagraphPortion>());
            }
        }
        public 形状片段 尾形状片段
        {
            get
            {
                if (_形状片段集体 == null || _形状片段集体.Count <= 0) return null;

                return new 形状片段(_形状片段集体.Last<IParagraphPortion>());
            }
        }

        public int 形状片段个数
        {
            get
            {
                if (_形状片段集体 == null) return 0;

                return _形状片段集体.Count;
            }
        }

        public 形状片段 添加文本形状片段(string text)
        {
            if (_形状片段集体 == null) return null;

            _形状片段集体.AddText(text);
            return new 形状片段(_形状片段集体.Last<IParagraphPortion>());
        }

        public void 添加行分隔形状()
        {
            if (_形状片段集体 == null) return;

            _形状片段集体.AddLineBreak();
        }
    }

    public class 布告板形状
    {
        public 布告板形状(Bullet bullet)
        {
            _布告板形状体 = bullet;
        }

        private Bullet _布告板形状体;

        public Bullet 布告板形状体
        {
            get { return _布告板形状体; }
        }

        public string 布告板修饰字符
        {
            get
            {
                if (_布告板形状体 == null) return null;

                return _布告板形状体.Character;
            }
            set
            {
                if (_布告板形状体 == null) return;

                _布告板形状体.Character = value;
            }
        }

        public string 布告板色彩值
        {
            get
            {
                if (_布告板形状体 == null) return null;

                return _布告板形状体.ColorHex;
            }
        }

        public string 布告板字体名
        {
            get
            {
                if (_布告板形状体 == null) return null;

                return _布告板形状体.FontName;
            }
            set
            {
                if (_布告板形状体 == null) return;

                _布告板形状体.FontName = value;
            }
        }

        public 布告板类型 布告板类型
        {
            get
            {
                if (_布告板形状体 == null) return 布告板类型.非布告板;

                switch (_布告板形状体.Type)
                {
                    case BulletType.Numbered: return 布告板类型.数字布告板;
                    case BulletType.Picture: return 布告板类型.图形布告板;
                    case BulletType.Character: return 布告板类型.字符布告板;
                    default: return 布告板类型.非布告板;
                }
            }
            set
            {
                if (_布告板形状体 == null) return;

                switch (value)
                {
                    case 布告板类型.数字布告板:
                        _布告板形状体.Type = BulletType.Numbered;
                        break;
                    case 布告板类型.图形布告板:
                        _布告板形状体.Type = BulletType.Picture;
                        break;
                    case 布告板类型.字符布告板:
                        _布告板形状体.Type = BulletType.Character;
                        break;
                    // case 布告板类型.非布告板:
                    default:
                        _布告板形状体.Type = BulletType.None;
                        break;
                }
            }
        }
    }

    public enum 布告板类型
    {
        数字布告板,
        图形布告板,
        字符布告板,
        非布告板
    }

    public class 形状字体
    {
        public 形状字体(ITextPortionFont font)
        {
            _形状字体本体 = font;
        }

        private ITextPortionFont _形状字体本体;

        public ITextPortionFont 形状字体本体
        {
            get { return _形状字体本体; }
        }

        public bool 形状字体是否加粗
        {
            get { return _形状字体本体.IsBold; }
            set { _形状字体本体.IsBold = value; }
        }
        public bool 形状字体是否倾斜
        {
            get { return _形状字体本体.IsItalic; }
            set { _形状字体本体.IsItalic = value; }
        }

        public 形状字体 置形状字体下划线类型(形状下划线类型 type = 形状下划线类型.形状单下划线)
        {
            if (_形状字体本体 == null) return this;

            _形状字体本体.Underline = 形状下划线.取形状下划线(type).形状下划线体;
            return this;
        }

        public 形状字体 置形状字号(decimal fontsize)
        {
            if (_形状字体本体 == null) return this;
            if (fontsize < 8) fontsize = 8;
            if (fontsize > 96) fontsize = 96;

            _形状字体本体.Size = fontsize;
            return this;
        }

        /// <summary>
        /// 用以决定字体上下标偏移题。
        /// </summary>
        /// <param name="offset">偏移量。</param>
        /// <returns></returns>
        public 形状字体 置形状字体偏移量(int offset)
        {
            if (_形状字体本体 == null) return this;

            _形状字体本体.OffsetEffect = offset;
            return this;
        }

        public int 取形状字体偏移量()
        {
            if (_形状字体本体 == null) return -1;

            return _形状字体本体.OffsetEffect;
        }

        public string 取形状字体色彩标记()
        {
            if (_形状字体本体 == null) return null;

            return _形状字体本体.Color.Hex;
        }

        public 形状字体 置形状字体英文名(string fontEnName)
        {
            if (_形状字体本体 == null) return this;

            _形状字体本体.LatinName = fontEnName;
            return this;
        }

        public string 取形状字体英文名()
        {
            if (_形状字体本体 == null) return null;

            return _形状字体本体.LatinName;
        }

        public 形状字体 置形状字体中文名(string fontCnName)
        {
            if (_形状字体本体 == null) return this;

            _形状字体本体.EastAsianName = fontCnName;
            return this;
        }

        public string 取形状字体中文名()
        {
            if (_形状字体本体 == null) return null;

            return _形状字体本体.EastAsianName;
        }

        public 形状字体 置形状字体色彩标记(string rgb)
        {
            if (_形状字体本体 == null) return this;

            if (string.IsNullOrWhiteSpace(rgb))
            {
                rgb = "000000";
            }
            else
            {
                rgb = rgb.Trim(new char[] { ' ', '　', '\t', '#' });
                if (rgb.Length != 6) rgb = "000000";  // 默认黑色
            }

            _形状字体本体.Color.Update("#" + rgb);
            return this;
        }
    }

    public enum 形状下划线类型
    {
        形状无下划线,
        形状文本下划线,
        形状单下划线,
        形状双下划线,
        形状重下划线,
        形状点下划线,
        形状重点下划线,
        形状划下划线,
        形状重划下划线,
        形状长划下划线,
        形状长重划下划线,
        形状点划下划线,
        形状重点划下划线,
        形状点点划下划线,
        形状重点点划下划线,
        形状波浪下划线,
        形状重波浪下划线,
        形状双波浪下划线,
    }

    public class 形状下划线
    {
        public 形状下划线(TextUnderlineValues underLine)
        {
            _形状下划线体 = underLine;
        }

        public static 形状下划线 取形状下划线(形状下划线类型 type)
        {
            switch (type)
            {
                case 形状下划线类型.形状文本下划线: return new 形状下划线(TextUnderlineValues.Words);
                case 形状下划线类型.形状单下划线: return new 形状下划线(TextUnderlineValues.Single);
                case 形状下划线类型.形状双下划线: return new 形状下划线(TextUnderlineValues.Double);
                case 形状下划线类型.形状重下划线: return new 形状下划线(TextUnderlineValues.Heavy);
                case 形状下划线类型.形状点下划线: return new 形状下划线(TextUnderlineValues.Dotted);
                case 形状下划线类型.形状重点下划线: return new 形状下划线(TextUnderlineValues.HeavyDotted);
                case 形状下划线类型.形状划下划线: return new 形状下划线(TextUnderlineValues.Dash);
                case 形状下划线类型.形状重划下划线: return new 形状下划线(TextUnderlineValues.DashHeavy);
                case 形状下划线类型.形状长划下划线: return new 形状下划线(TextUnderlineValues.DashLong);
                case 形状下划线类型.形状长重划下划线: return new 形状下划线(TextUnderlineValues.DashLongHeavy);
                case 形状下划线类型.形状点划下划线: return new 形状下划线(TextUnderlineValues.DotDash);
                case 形状下划线类型.形状重点划下划线: return new 形状下划线(TextUnderlineValues.DotDashHeavy);
                case 形状下划线类型.形状点点划下划线: return new 形状下划线(TextUnderlineValues.DotDotDash);
                case 形状下划线类型.形状重点点划下划线: return new 形状下划线(TextUnderlineValues.DotDotDashHeavy);
                case 形状下划线类型.形状波浪下划线: return new 形状下划线(TextUnderlineValues.Wavy);
                case 形状下划线类型.形状重波浪下划线: return new 形状下划线(TextUnderlineValues.WavyHeavy);
                case 形状下划线类型.形状双波浪下划线: return new 形状下划线(TextUnderlineValues.WavyDouble);
                default: return new 形状下划线(TextUnderlineValues.None);
            }
        }

        private TextUnderlineValues _形状下划线体;

        public TextUnderlineValues 形状下划线体
        {
            get { return _形状下划线体; }
        }
    }

    public class 图形形状 : 形状
    {
        public 图形形状(IPicture picture) : base(picture)
        {
            _图形形状体 = picture;
        }

        private IPicture _图形形状体;

        public IPicture 图形形状体
        {
            get { return _图形形状体; }
        }

        public 图形形状 置图像文件(string path)
        {
            if (_图形形状体 == null) return this;
            if (File.Exists(path) == false) return this;

            var img = new Bitmap(path);
            MemoryStream stream = new MemoryStream();
            img.Save(stream, ImageFormat.Bmp);
            _图形形状体.Image.Update(stream);
            stream.Close();
            return this;
        }
    }

    public class 幻灯片母版集
    {
        public 幻灯片母版集(ISlideMasterCollection slideMasters)
        {
            _幻灯片母版集体 = slideMasters;
        }

        private ISlideMasterCollection _幻灯片母版集体;

        public ISlideMasterCollection 幻灯片母版集体
        {
            get { return _幻灯片母版集体; }
        }
    }

    public class 幻灯片区块
    {
        public 幻灯片区块(ISection section)
        {
            _幻灯片区块体 = section;
        }

        private ISection _幻灯片区块体;

        public ISection 幻灯片区块体
        {
            get { return _幻灯片区块体; }
        }

        public string 幻灯片区块名称
        {
            get { return _幻灯片区块体.Name; }
        }
    }

    public class 幻灯片区块集
    {
        public 幻灯片区块集(ISections sections)
        {
            _幻灯片区块集体 = sections;
        }

        private ISections _幻灯片区块集体;

        public ISections 幻灯片区块集体
        {
            get { return _幻灯片区块集体; }
        }
    }

    public class 幻灯片页脚
    {
        public 幻灯片页脚(IFooter footer)
        {
            _幻灯片页脚体 = footer;
        }

        public IFooter _幻灯片页脚体;

        public IFooter 幻灯片页脚体
        {
            get { return _幻灯片页脚体; }
        }

        public 幻灯片页脚 添加幻灯片序号()
        {
            if (_幻灯片页脚体 == null) return this;

            _幻灯片页脚体.AddSlideNumber();
            return this;
        }

        public 幻灯片页脚 删除幻灯片页脚()
        {
            if (_幻灯片页脚体 == null) return this;

            _幻灯片页脚体.RemoveSlideNumber();
            return this;
        }

        public 幻灯片页脚 移除幻灯片页脚()
        {
            if (_幻灯片页脚体 == null) return this;

            _幻灯片页脚体.RemoveSlideNumber();
            return this;
        }
    }

    public enum 幻灯片布局
    {
        空白布局,
        图表布局,
        图表和文本布局,
        剪贴画和文本布局,
        剪贴画与竖排文本布局,
        自定义布局,
        示意图布局,
        四对象布局,
        多媒体与文本布局,
        对象布局,
        单对象和双对象布局,
        对象和文本布局,
        仅对象布局,
        对象在文本上布局,
        对象文本布局,
        图形与标题布局,
        区块头布局,
        表布局,
        标题布局,
        仅标题布局,
        双列文本布局,
        双对象布局,
        双对象和单对象布局,
        双对象和文本布局,
        双对象在文本上布局,
        双文本和双对象布局,
        文本布局,
        文本和图表布局,
        文本和剪贴画布局,
        文本和多媒体布局,
        文本和对象布局,
        文本和双对象布局,
        文本在对象上布局,
        竖排标题和文本布局,
        竖排标题和文本在图表上布局,
        竖排文本布局,
    }
}
